home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / General / GCC 1.37.1r15 / Machines / out-mips.c < prev    next >
Text File  |  1990-03-14  |  12KB  |  523 lines

  1. /* Subroutines for insn-output.c for MIPS
  2.    Contributed by A. Lichnewsky, lich@inria.inria.fr.
  3.    Copyright (C) 1989 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 1, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21.  
  22. #include <stdio.h>
  23. extern void  my_print_rtx ();
  24. extern void  abort_with_insn ();
  25.  
  26.  
  27. /* Global variables for machine-dependent things.  */
  28.  
  29. char *reg_numchar[] = REGISTER_NUMCHAR;
  30.  
  31. /* When eliminating the frame pointer, this is the size of the frame
  32.    aside from explicit stack slots.  */
  33. int frame_stack_difference;
  34.  
  35. /* Return truth value of whether OP can be used as an operands
  36.    where a 16 bit integer is needed  */
  37.  
  38. int
  39. arith_operand (op, mode)
  40.      rtx op;
  41.      enum machine_mode mode;
  42. {
  43.   return (register_operand (op, mode)
  44.       || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
  45. }
  46.  
  47. /* Return truth value of whether OP can be used as an operand in a two
  48.    address arithmetic insn (such as set 123456,%o4) of mode MODE.  */
  49.  
  50. int
  51. arith32_operand (op, mode)
  52.      rtx op;
  53.      enum machine_mode mode;
  54. {
  55.   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
  56. }
  57.  
  58. /* Return truth value of whether OP is a integer which fits in 16 bits  */
  59.  
  60. int
  61. small_int (op, mode)
  62.      rtx op;
  63.      enum machine_mode mode;
  64. {
  65.   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
  66. }
  67.  
  68.  
  69. #if 0
  70.                 /* Used to allow constant expression known
  71.                 ** only at assembly time
  72.                 */
  73. int
  74. legitimize_constant_expr(expr)
  75.      rtx expr;
  76. {
  77.   if (GET_CODE (expr) == PLUS
  78.       ||
  79.       GET_CODE (expr) == MINUS)
  80.     return (BASIC_CONSTANT_P (XEXP (expr, 0))
  81.         && BASIC_CONSTANT_P (XEXP (expr, 1)));
  82.   return 0;
  83. }
  84. #endif
  85.  
  86. char *
  87. output_load_immediate (operands)
  88.      rtx *operands;
  89. {
  90.   rtx xops[3];
  91.   xops[0] = operands[0];
  92.   xops[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]));
  93.  
  94.   if ((INTVAL (operands[1]) >> 16)
  95.       && (INTVAL (operands[1]) & 0xffff))
  96.     {
  97.       if (!((-INTVAL (operands[1])) >> 16))
  98.     {
  99.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  100.                  (INTVAL (operands[1])) & 0xffff);
  101.       output_asm_insn ("addi%:\t%0,$0,%x1\t#movsi low part of %2",
  102.                xops);
  103.     }
  104.       else
  105.     {
  106.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  107.                  (INTVAL (operands[1]))>>16);
  108.       output_asm_insn ("lui\t%0,%x1\t#movsi high part of %2", xops);
  109.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  110.                  (INTVAL (operands[1])) & 0xffff);
  111.       output_asm_insn ("ori\t%0,%x1\t#movsi low part of %2", xops);
  112.     }
  113.     }
  114.   else if (INTVAL (operands[1]) >> 16)
  115.     {
  116.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  117.              (INTVAL (operands[1]))>>16);
  118.       output_asm_insn ("lui\t%0,%x1\t#movsi high part of %2", xops);
  119.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  120.              (INTVAL (operands[1])) & 0xffff);
  121.     }
  122.   else
  123.     {
  124.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  125.              (INTVAL (operands[1])) & 0xffff);
  126.       output_asm_insn ("ori\t%0,$0,%x1\t#movsi low part of %2",
  127.                xops);
  128.     }
  129.   return "";
  130. }
  131.  
  132.                 /* Used to obtain address of subregs      */
  133.                 /* when in memory. This takes mode and    */
  134.                 /* subreg number into account             */
  135.  
  136. rtx
  137. addr_compensate (addr, submode, origmode, subnum)
  138.      rtx addr;
  139.      enum machine_mode submode;
  140.      enum machine_mode origmode;
  141.      int subnum;
  142. {
  143.   extern rtx change_address ();
  144.   extern rtx plus_constant ();
  145.  
  146.   if (submode == QImode && origmode == SImode)
  147.     {
  148. #ifdef BYTES_BIG_ENDIAN
  149.       return change_address (addr, QImode,
  150.                  plus_constant (XEXP (addr, 0), 3 - subnum));
  151. #else
  152.       return change_address (addr, QImode,
  153.                  plus_constant (XEXP (addr, 0), subnum));
  154. #endif
  155.     }
  156.   else if (submode == HImode && origmode == SImode)
  157.     {
  158. #ifdef BYTES_BIG_ENDIAN
  159.       return change_address (addr, HImode,
  160.                  plus_constant (XEXP (addr, 0), 2 - 2*subnum));
  161. #else
  162.       return change_address (addr, HImode,
  163.                  plus_constant (XEXP (addr, 0), subnum));
  164. #endif
  165.     }
  166.   else
  167.     abort_with_insn (addr, "addr_compensate does not support mode");
  168. }
  169.  
  170.  
  171.  
  172.  
  173.                 /* VARARGS */
  174. int function_suspect;
  175. int varargs_suspect = 0;
  176. int this_varargs_suspect;
  177.  
  178.                 /* PARAMETER LIST CONSTRUCTION */
  179.  
  180.  
  181. static struct
  182. {
  183.   enum arg_state nxs_if_f, nxs_if_g;
  184.   short reg_if_f, reg_if_g;
  185. }
  186.   arg_state_table[(int) (ARG_STA_GGGG + 1)]  = ARG_STA_AUTOMA;
  187.  
  188.  
  189.  
  190.                 /* For use in Frame/ Stack pointer management*/
  191. char * current_function_name;
  192. int current_function_total_framesize;
  193. typedef CUMULATIVE_ARGS cumulative_args;
  194.  
  195. enum arg_state
  196. function_arg_advance (cum, mode, type)
  197.      cumulative_args *cum;
  198.      enum machine_mode mode;
  199.      int type;
  200. {
  201.   cum->arg_rec_state
  202.     = (FP_REGS == PREFERRED_RELOAD_CLASS_FM (mode, GR_REGS)
  203.        ? arg_state_table[(int)((cum->arg_rec_state))].nxs_if_f
  204.        : arg_state_table[(int)((cum->arg_rec_state))].nxs_if_g);
  205.  
  206.   (cum->arg_num)++;
  207. }
  208.  
  209. rtx
  210. function_arg (cum, mode, type, named)
  211.      cumulative_args *cum;
  212.      enum machine_mode mode;
  213.      int type;
  214.      int named;
  215. {
  216.   int regnum;
  217.  
  218.   regnum
  219.     = (FP_REGS == PREFERRED_RELOAD_CLASS_FM (mode, GR_REGS)
  220.        ? arg_state_table[(int)((cum->arg_rec_state))].reg_if_f
  221.        : arg_state_table[(int)((cum->arg_rec_state))].reg_if_g);
  222.  
  223.   if (mode == BLKmode)
  224.     return 0;
  225.   else if (regnum >= 0)
  226.     return gen_rtx (REG, mode, regnum);
  227.   else if (regnum == -2)
  228.     {
  229.       if (mode == SFmode)
  230.     return gen_rtx (SUBREG, SFmode, gen_rtx (REG, DFmode, 6), 0);
  231.       else
  232.     return gen_rtx (REG, DFmode, 6);
  233.     }
  234.   else
  235.     return 0;
  236. }
  237.  
  238.  
  239.  
  240. static  rtx branch_cmp_op[2];
  241. static  enum machine_mode branch_cmp_mode;
  242.  
  243. compare_collect (mode, op0, op1)
  244.      enum machine_mode mode;
  245.      rtx op0;
  246.      rtx op1;
  247. {
  248.   if (TARGET_DEBUGD_MODE)
  249.     {
  250.       fprintf (stderr, "compare_collect mode = %d, operands::", mode);
  251.       my_print_rtx (op0);
  252.       my_print_rtx (op1);
  253.     }
  254.   branch_cmp_op[0] = op0;
  255.   branch_cmp_op[1] = op1;
  256.   branch_cmp_mode = mode;
  257. }
  258.  
  259.  
  260. compare_restore (operands, mode, insn)
  261.      rtx *operands;
  262.      enum machine_mode *mode;
  263.      rtx insn;
  264. {
  265.   rtx  previous;
  266.   rtx  prev_par;
  267.   if (TARGET_DEBUGD_MODE)
  268.     {
  269.       fprintf (stderr, "compare_restore returning mode = %d, operands:%X,%X:",
  270.            branch_cmp_mode, branch_cmp_op[0], branch_cmp_op[1]);
  271.       my_print_rtx (branch_cmp_op[0]);
  272.       my_print_rtx (branch_cmp_op[1]);
  273.     }
  274.  
  275.   if ((! branch_cmp_op[0]) && (! branch_cmp_op[1]))
  276.     {
  277.       /*  Signal that multiple branches following */
  278.       /* a comparison have been found             */
  279.       if (TARGET_DEBUGD_MODE)
  280.     {
  281.       fprintf (stderr, "Not at ease in compare_restore\n");
  282.       my_print_rtx (insn);
  283.       my_print_rtx (PREV_INSN (insn));
  284.     }
  285.       /*  Find the previous comparison */
  286.       while ((GET_CODE (PREV_INSN (insn))) == JUMP_INSN)
  287.     {
  288.       insn = PREV_INSN (insn);
  289.       if (TARGET_DEBUGD_MODE)
  290.         my_print_rtx (PREV_INSN (insn));
  291.     }
  292.  
  293.       previous =  PATTERN (PREV_INSN (insn));
  294.  
  295.       if ((GET_CODE (previous)) == PARALLEL)
  296.     {
  297.       /*  Signal  that we have a very strange */
  298.       /* RTL construct,... usually generated  */
  299.       /* by the optimizer, that seems to      */
  300.       /* contradict the documentation         */
  301.  
  302.       /* However, this construct holds the    */
  303.       /* correct information in a very reliable */
  304.       /* way */
  305.  
  306.       branch_cmp_op[0] = XVECEXP (previous, 0, 0);
  307.       branch_cmp_op[1] = XVECEXP (previous, 0, 1);
  308.       /*       warning ("Check branch optimization with -mdebugd");
  309.        */
  310.     }
  311.       else
  312.     if (((GET_CODE (previous)) == SET)
  313.         &&
  314.         ((GET_CODE (XEXP (previous, 0))) == CC0)
  315.         &&
  316.         ((GET_CODE (XEXP (previous, 1))) == COMPARE))
  317.       {            /* Here we find the comparison info    */
  318.         /* in a more classical format          */
  319.  
  320.         previous = XEXP (previous, 1);
  321.         branch_cmp_op[0] = XEXP (previous, 0);
  322.         branch_cmp_op[1] = XEXP (previous, 1);
  323.       }
  324.           else
  325.       {            /* Be prepared for other things popping out */
  326.         abort ();
  327.       }
  328.     }
  329.  
  330.  
  331.  
  332.   if (!  branch_cmp_op[0])
  333.     operands[0] = gen_rtx (REG, VOIDmode, 0);
  334.   else
  335.     operands[0] = branch_cmp_op[0];
  336.   if (!  branch_cmp_op[1])
  337.     operands[1] = gen_rtx (REG, VOIDmode, 0);
  338.   else
  339.     operands[1] = branch_cmp_op[1];
  340.   *mode = branch_cmp_mode;
  341.  
  342.   branch_cmp_op[0] = NULL;
  343.   branch_cmp_op[1] = NULL;
  344.  
  345. }
  346.  
  347. #if 0
  348.                 /* See flags.h and toplev.c */
  349. extern int optimize;
  350. extern int flag_combine_regs;
  351. extern int flag_strength_reduce;
  352. extern int flag_no_peephole;
  353. extern int flag_inline_functions;
  354. extern int flag_omit_frame_pointer;
  355. extern char *main_input_filename;
  356. extern char *asm_file_name;
  357.                 /* See c-tree.h  and c-decl.c */
  358. extern int flag_signed_char;
  359.  
  360. #include <time.h>
  361. #include <sys/types.h>
  362. #include <sys/timeb.h>
  363.  
  364. void
  365. print_options (out)
  366.      FILE *out;
  367. {
  368.   char *a_time;
  369.   long c_time;
  370.  
  371.   fprintf (out, " #OPTIONS:\t%s%s%s%s%s%s%s\n",
  372.        (TARGET_NOFIXED_OVFL ? " -dnofixed-ovfl":" -dfixed-ovfl"),
  373.        (optimize ? " optimize" : ""),
  374.        (flag_combine_regs ? " -fcombine-regs" : " !combine-regs"),
  375.        (flag_strength_reduce ? "" : " !strength_reduce"),
  376.        (flag_omit_frame_pointer ?"" :" !omit_frame_pointer"),
  377.        (flag_no_peephole ? "" : " peephole"),
  378.        (flag_inline_functions ?" inline-functions":""));
  379.   fprintf (out, " #OPTIONS:\t%s%s\n",
  380.        (flag_signed_char ? " signed-char" : " !signed-char"),
  381.        (TARGET_GP_OPT    ? " gpOPT"      : " !gpOPT"));
  382.   fprintf (out, " #Source:\t%s\n", main_input_filename);
  383.   fprintf (out, " #Destination:\t%s\n", asm_file_name);
  384.   c_time = time (0);
  385.   a_time = ctime (&c_time);
  386.   fprintf (out, " #Compiled:\t%s", a_time);
  387. #ifdef __GNUC__
  388. #ifndef __VERSION__
  389. #define __VERSION__ "[unknown]"
  390. #endif
  391.   fprintf (out, " # (META)compiled by GNU C version %s.\n", __VERSION__);
  392. #else
  393.   fprintf (out, " # (META)compiled by CC.\n");
  394. #endif
  395. }
  396.  
  397.                 /* DEBUGGING UTILITIES */
  398. rtx al_log_insn_debug;
  399.  
  400. abort_show_logged ()
  401. {
  402.   if (al_log_insn_debug)
  403.     my_print_rtx (al_log_insn_debug);
  404.   abort ();
  405. }
  406.  
  407. extern FILE *outfile;
  408.  
  409. void
  410. my_print_rtx (in_rtx)
  411.      register rtx in_rtx;
  412. {
  413.   FILE *old;
  414.   old = outfile;
  415.  
  416.   outfile = stderr;
  417.   print_rtx (in_rtx);
  418.   fprintf (outfile, "\n");
  419.  
  420.   outfile = old;
  421. }
  422.  
  423. void
  424. my_print_insncode (insn)
  425.      rtx insn;
  426. {
  427.   FILE *old;
  428.   old = outfile;
  429.  
  430.   outfile = stderr;
  431.   print_rtx (insn);
  432.   fprintf (outfile, "\n");
  433.   fprintf (outfile, "INSN_CODE (insn) = %X\n", INSN_CODE (insn));
  434.  
  435.   outfile = old;
  436. }
  437.  
  438. void
  439. abort_with_insn (insn, reason)
  440.      rtx insn;
  441.      char *reason;
  442. {
  443.   fprintf (stderr, "About to Abort::%s\n", reason);
  444.   my_print_rtx (insn);
  445.   abort ();
  446. }
  447. #endif
  448.  
  449. void
  450. abort_with_insn ()
  451. {
  452.   abort ();
  453. }
  454.  
  455. void
  456. my_print_rtx (in_rtx)
  457.      register rtx in_rtx;
  458.  
  459. {
  460.   abort();
  461. }
  462.  
  463. #include "tree.h"
  464.                 /* GET SECTION (DATA/SDATA) THRESHOLD */
  465. int mips_section_threshold = -1;
  466.  
  467. extern char *tree_code_name[];
  468.  
  469. int
  470. mips_section_get ()
  471. {
  472.   register int i;
  473.   if (mips_section_threshold == -1)
  474.     {
  475.       i = TARGET_GVALUE;
  476.       if (i >= 6) i += 3;
  477.       if ((1 << i) != MIPS_GVALUE_DEFAULT)
  478.     warning ("G value this run == %d\n", 1 << i);
  479.       mips_section_threshold = 1 << i;
  480.     }
  481.  
  482.   return mips_section_threshold;
  483. }
  484.  
  485. int
  486. mips_output_external (file, tree_exp, name)
  487.      FILE *file;
  488.      tree tree_exp;
  489.      char *name;
  490. {
  491.   register int i;
  492.   if (TARGET_GP_OPT
  493.       && ((TREE_CODE (tree_exp)) != FUNCTION_DECL)
  494.       &&
  495.       ((i = int_size_in_bytes (TREE_TYPE (tree_exp))) > 0))
  496.     {
  497.       fputs ("\n#ifndef _gccx__", file);
  498.       assemble_name (file, name);
  499.       fputs ("\n.extern\t", (file));
  500.       assemble_name ((file), (name));
  501.       fprintf ((file), ", %d", i, (TREE_TYPE (tree_exp)));
  502.       fputs ("\n#define _gccx__", file);
  503.       assemble_name (file, name);
  504.       fputs ("\n#endif\n ", file);
  505.     }
  506.   return 0;
  507. }
  508.  
  509. extern char *asm_file_name;
  510.  
  511. int
  512. mips_asm_file_end (file)
  513.      FILE *file;
  514. {
  515.   if (TARGET_GP_OPT)
  516.     {
  517.       fprintf (file, "\n#else\n#ifndef %sRESCAN_GCC", "__x_");
  518.       fprintf (file, "\n#define %sRESCAN_GCC\n#include \"%s\"", "__x_",
  519.            asm_file_name);
  520.       fprintf (file, "\n#endif\n#endif\n");
  521.     }
  522. }
  523.